// nptr = Module.findExportByName(null, name);
// hook il2cpp_class_get_methods,可以获取到set_TimeScale的偏移
// Interceptor.attach(Module.findExportByName("op", "il2cpp_class_from_name"), {
// 	onEnter: function (args) {
//         // console.log("ddd", Memory.readFloat(args[0]));
//         // console.log(base_addr.add(m[0]))
//         // console.log(args[1], 'be called')
//         // args[0].replace(4.0)
//         // console.log("il2cpp_class_from_name namespace", Memory.readUtf8String(args[1]));
//         // console.log("il2cpp_class_from_name name", Memory.readUtf8String(args[2]));

//     },
//     onLeave: function (ret) {
//         // console.log("ret = ", ret)
//     }
// })

var base = Module.findBaseAddress("op")
console.log('base = ', base)
var isInControl = false;
var isHostPlayerMoving = false;
// var set_timeScale_real = 0x0;
// Interceptor.attach(base.add(0x2BB24BC), {
// 	onEnter: function (args) {
// 		if (Memory.readUtf8String(args[1]) == "JoyStickOnMove") {
// 			console.log("il2cpp_class_get_method_from_name methodname", Memory.readUtf8String(args[1]));
// 	   		console.log("il2cpp_class_get_method_from_name args number", args[2]);
// 		}
// 		if (Memory.readUtf8String(args[1]) == "JoyStickOnStop") {
// 			console.log("il2cpp_class_get_method_from_name methodname", Memory.readUtf8String(args[1]));
// 	   		console.log("il2cpp_class_get_method_from_name args number", args[2]);
// 		}
	    
// 	},
// 	onLeave: function (ret) {
// 	    // console.log("ret = ", ret)
// 	}
// })

var set_timeScale = 0x0;
var get_timeScale = 0x0;
Interceptor.attach(Module.findExportByName("op", "il2cpp_add_internal_call"), {
	onEnter: function (args) {
        // console.log("ddd", Memory.readFloat(args[0]));
        // console.log(base_addr.add(m[0]))
        // console.log(args[1], 'be called')
        // args[0].replace(4.0)
        var func = Memory.readUtf8String(args[0]);
        if (func == "UnityEngine.Time::set_timeScale") {
            console.log("il2cpp_class_from_name namespace", Memory.readUtf8String(args[0]));
            console.log("il2cpp_class_from_name name", args[1]);
            set_timeScale = args[1]
            var set = new NativeFunction(set_timeScale, 'void', ['float']);
            console.log('set = ', set)

            Interceptor.replace(set_timeScale, new NativeCallback((timeScale)=> {
                console.log("set_timeScale before = ", timeScale);
                timeScale = 4.0;
                const result = set(timeScale);
                console.log("set_timeScale after = ", timeScale);
                return result;
            }, 'void', ['float']));

            // var curTimeScale = 4.0;
            // var result = set(curTimeScale)
            // Interceptor.attach(set_timeScale, {
            //     onEnter: function (args) {
            //         console.log("ddd", Memory.readFloat(args[0]));
            //         // console.log(base_addr.add(m[0]))
            //         console.log(args[1], 'be called')
            //         // args[0].replace(4.0)

            //     },
            //     onLeave: function (ret) {
            //         // console.log("ret = ", ret)
            //     }
            // })
            // var addr = args[1];
            // var set_timeScale = args[1] - base;
            // console.log('set_timeScale = ', set_timeScale);
        }
        if (func == "UnityEngine.Time::get_timeScale") {
            console.log("il2cpp_class_from_name namespace", Memory.readUtf8String(args[0]));
            console.log("il2cpp_class_from_name name", args[1]);
            get_timeScale = args[1];
            const get = new NativeFunction(get_timeScale, 'float', []);
            Interceptor.replace(get_timeScale, new NativeCallback(()=> {
                const timeScale = get();
                // console.log("get_timeScale = ", timeScale);
                return timeScale;
            }, 'float', []))
            // Interceptor.attach(get_timeScale, {
            //     onEnter: function (args) {

            //     },
            //     onLeave: function (ret) {
            //         // console.log("ret = ", Memory.readFloat(ret))
            //         console.log("ret readFloat = ", ret.readFloat())
            //         console.log("ret readDouble = ", ret.readDouble())
            //         // console.log("ret = ", hexdump(ret))
            //     }
            // })
            // var addr = args[1];
            // var set_timeScale = args[1] - base;
            // console.log('set_timeScale = ', set_timeScale);
        }
        // console.log("j__il2cpp_add_internal_call name", Memory.readUtf8String(args[0]));
        // console.log("j__il2cpp_add_internal_call function", args[1]);

    },
    onLeave: function (ret) {
        // console.log("ret = ", ret)
    }
})

console.log("set_timeScale ", base.add(0x2D46B44))
var set_timeScale_real = new NativeFunction(base.add(0x2D46B44), 'void', ['float']);
// Interceptor.attach(base.add(0x2D46B44), {


// // Interceptor.attach(base.add(0x2bb300c), {
// // 	onEnter: function (args) {
// //         console.log("ddd", Memory.readUtf8String(args[0]));
// //         // console.log(base_addr.add(m[0]))
// //         console.log(args[1], 'be called')
// //         // args[0].replace(4.0)

// //     },
// //     onLeave: function (ret) {
// //         console.log("ret = ", ret)
// //     }
// // })
console.log("get_timeScale ", base.add(0x2d46b2c))
console.log("set_timeScale_real = ", set_timeScale_real)
function GSpeed(timeScale)
{
    if (set_timeScale_real)
    {
        set_timeScale_real(timeScale)
    }
}

var isAutoPathing = false;
var isRunning = false;
// enum StateTypeDef
var GameObj_InState = new NativeFunction(base.add(0x481C84), 'bool', ['pointer', 'int']);
var GameObj_IsHostPlayer = new NativeFunction(base.add(0x483E0C), 'bool', ['pointer']);
var curSpeed = 4.0;

Interceptor.replace(base.add(0x481C84), new NativeCallback((thiz, state)=> {
    // console.log("GameObj_InState replace arg 2 = ", state);

    const result = GameObj_InState(thiz, state);
    // console.log("GameObj_InState replace = ", result);
    if (state == 2) {
        isAutoPathing = result;
    }
    if (state == 16384) {
        isRunning = result;
    }
    return result;
}, 'bool', ['pointer', 'int']))

// SpeedChangeDelegate_Invoke
var SpeedChangeDelegate_Invoke = new NativeFunction(base.add(0x483EC0), 'void', ['pointer', 'float']);
Interceptor.replace(base.add(0x483EC0), new NativeCallback((thiz, speed)=> {
    console.log("SpeedChangeDelegate_Invoke replace  speed = ", speed);

    const result = SpeedChangeDelegate_Invoke(thiz, speed);
    return result;
}, 'void', ['pointer', 'float']))

// hook GameObj_onUpdate
var GameObj_onUpdate = new NativeFunction(base.add(0x481B14), 'void', ['pointer']);
Interceptor.replace(base.add(0x481B14), new NativeCallback((thiz)=> {
    // console.log("GameObj_onUpdate replace  ");
    var moveSpeedAddr = thiz.add(0x11C);
    // console.log("GameObj_onUpdate replace moveSpeedAddr ", moveSpeedAddr);
    // console.log('moveSpeed = ', moveSpeedAddr.readFloat());
    var jumpStateFlag = thiz.add(0xA8);
    console.log('jumpStateFlag = ', jumpStateFlag.readU8());
    if(isHostPlayerMoving){
        // *(float*)(thiz + 0x11C) = 6.0;
        // args[0] + 0x11C = 6.0;
        var newSpeed = moveSpeedAddr.readFloat();
        newSpeed = 6.0;
    }
    else{
        if(!GameObj_IsHostPlayer(thiz)) {
            // var isRunning = GameObj_InState(args[0], 16384);
            // var isAutoPathing = GameObj_InState(args[0], 2);
            // var isMoving = GameObj_InState(args[0], 4);
            // var isIdle = GameObj_InState(args[0], 4096);
            // // LOGD("isRunning = %d", isRunning);
            // // LOGD("isAutoPathing = %d", isAutoPathing);
            // console.log('isIdle = ', isIdle);
            // console.log('isMoving = ', isMoving);
            // console.log('isRunning = ', isRunning);
            // console.log('isAutoPathing = ', isAutoPathing);
            if((isRunning || isAutoPathing)){

                console.log('isAutoPathing = ', isAutoPathing);
                var newSpeed = moveSpeedAddr.readFloat();
                console.log('newSpeed = ', newSpeed);
                newSpeed = 1.5;
            // if(6.0 / GSpeed < 1){
            //   *(float*)(thiz + 0xB4) = 1;
            // }else{
            //   *(float*)(thiz + 0xB4) = 6.0 / GSpeed;
            // }
            // *(float*)(thiz + 0xB4) = 6.0 / GSpeed;
                // if(curSpeed > 2.0){
                //     args[0] + 0x11C = 5.5 - 6.0 / curSpeed;
                // }else{
                //     args[0] + 0x11C = 6.0;
                // }

            } else {
            // if(GSpeed >= 1.6){
            //   *(float*)(thiz + 0xB4) = 16 - GSpeed;
            // }
            // else{
            //   *(float*)(thiz + 0xB4) = 6.0 / GSpeed;
            // }
            // *(float*)(thiz + 0xB4) =  GSpeed + 6;
                // if(curSpeed > 2.0){
                //     args[0] + 0x11C = 5.0;
                // }else{
                //     args[0] + 0x11C = 6.0;
                // }

            }
        }
    }
    const result = GameObj_onUpdate(thiz);
    return result;
}, 'void', ['pointer']))
// Interceptor.attach(base.add(0x481B14), {
//   onEnter: function (args) {
//         // console.log("GameObj_onUpdate")
//         if(isHostPlayerMoving){
//             // *(float*)(thiz + 0x11C) = 6.0;
//             // args[0] + 0x11C = 6.0;
//         }
//         else{
//             if(!GameObj_IsHostPlayer(args[0])) {
//                 // var isRunning = GameObj_InState(args[0], 16384);
//                 // var isAutoPathing = GameObj_InState(args[0], 2);
//                 // var isMoving = GameObj_InState(args[0], 4);
//                 // var isIdle = GameObj_InState(args[0], 4096);
//                 // // LOGD("isRunning = %d", isRunning);
//                 // // LOGD("isAutoPathing = %d", isAutoPathing);
//                 // console.log('isIdle = ', isIdle);
//                 // console.log('isMoving = ', isMoving);
//                 // console.log('isRunning = ', isRunning);
//                 // console.log('isAutoPathing = ', isAutoPathing);
//                 if((isRunning || isAutoPathing)){
//                     var moveSpeed = args[0].add(0x11C).readPointer();
//                     console.log('isAutoPathing = ', isAutoPathing);
//                     console.log('ss = ', moveSpeed.readFloat());
//                 // if(6.0 / GSpeed < 1){
//                 //   *(float*)(thiz + 0xB4) = 1;
//                 // }else{
//                 //   *(float*)(thiz + 0xB4) = 6.0 / GSpeed;
//                 // }
//                 // *(float*)(thiz + 0xB4) = 6.0 / GSpeed;
//                     // if(curSpeed > 2.0){
//                     //     args[0] + 0x11C = 5.5 - 6.0 / curSpeed;
//                     // }else{
//                     //     args[0] + 0x11C = 6.0;
//                     // }

//                 } else {
//                 // if(GSpeed >= 1.6){
//                 //   *(float*)(thiz + 0xB4) = 16 - GSpeed;
//                 // }
//                 // else{
//                 //   *(float*)(thiz + 0xB4) = 6.0 / GSpeed;
//                 // }
//                 // *(float*)(thiz + 0xB4) =  GSpeed + 6;
//                     // if(curSpeed > 2.0){
//                     //     args[0] + 0x11C = 5.0;
//                     // }else{
//                     //     args[0] + 0x11C = 6.0;
//                     // }

//                 }
//             }
//         }
//     },
//     onLeave: function (ret) {

//     }
// })

// SceneBase_JoyStickOnMove_hook
Interceptor.attach(base.add(0x4C8920), {
  onEnter: function (args) {
        console.log('SceneBase_JoyStickOnMove_hook')
        GSpeed(1.0);
        isInControl = true;
        isHostPlayerMoving = true;
    },
    onLeave: function (ret) {

    }
})

// SceneBase_JoyStickOnStop_hook
Interceptor.attach(base.add(0x4C8B00), {
  onEnter: function (args) {
        console.log('SceneBase_JoyStickOnStop_hook')
        if(isInControl){
            console.log("isInControl");

            GSpeed(4.0);
            isInControl = false;
            isHostPlayerMoving = false;
          }
    },
    onLeave: function (ret) {

    }
})

// BattleManager_Begin_hook
Interceptor.attach(base.add(0xB3265C), {
  onEnter: function (args) {
        console.log('BattleManager_Begin_hook')

        GSpeed(4.0);
        isHostPlayerMoving = false;
    },
    onLeave: function (ret) {

    }
})


var StateControllerBase_IsHostPlayer = new NativeFunction(base.add(0x519C28), 'bool', ['pointer']);
var StateControllerBase_IsMovementStateStop = new NativeFunction(base.add(0x519A60), 'bool', ['pointer']);
// StateControllerBase_AddState_hook
Interceptor.attach(base.add(0x519510), {
  onEnter: function (args) {
                // args[0].replace(4.0)
        console.log('StateControllerBase_AddState_hook')
        if(StateControllerBase_IsHostPlayer(args[0])){
        // LOGD("call StateControllerBase_AddState_hook a2 = %d", a2);
            if(args[2] == 2 || args[2] == 16384){

                GSpeed(1.0);
                isHostPlayerMoving = true;
            }else if(args[2] == 4096){

                GSpeed(4.0);
                isHostPlayerMoving = false;
            }
        }
    },
    onLeave: function (ret) {

    }
})

// StateControllerBase_StopState_hook
Interceptor.attach(base.add(0x519778), {
  onEnter: function (args) {

        console.log('StateControllerBase_StopState_hook');
        if(StateControllerBase_IsHostPlayer(args[0])){
        // LOGD("call StateControllerBase_StopState_hook a2 = %d", a2);
        //卡墙调整方向有点跳跃，再加IsMovementStateStop的判断,测试没用。。。
        // if(a2 == 16384 && StateControllerBase_IsMovementStateStop(thiz) == 0){
        //   LOGD("can not change speed");
        //   canSpeedUp = false;
        //   time_setTimeScale_f(1.0);
        //   return StateControllerBase_StopState_f(thiz, a1, a2, a3, a4);
        // }
            if(args[2] == 16384 || args[2] == 2){
            // LOGD("StateControllerBase_IsMovementStateStop = %d", StateControllerBase_IsMovementStateStop(thiz));

                GSpeed( 4.0 );
                isHostPlayerMoving = false;
            }
        }
    },
    onLeave: function (ret) {

    }
})

// get_CurrentStateType_hook
Interceptor.attach(base.add(0x5195B4), {
  onEnter: function (args) {

        console.log('StateControllerBase_get_CurrentStateType_hook');

    },
    onLeave: function (ret) {
        // console.log('StateControllerBase_get_CurrentStateType_hook  state ', hexdump(ret));
    }
})



